package com.jy.wms.common.aop;

import com.jy.wms.common.IPUtil;
import com.jy.wms.common.UUIDUtils;
import com.jy.wms.common.annotions.BaseServiceDescribe;
import com.jy.wms.common.base.SessionInfo;
import com.jy.wms.dao.SysLogMapper;
import com.jy.wms.pojo.SysLog;
import com.jy.wms.pojo.SysUser;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 记录service方法调用的日志
 */
@Configuration
@Aspect//该标签把LoggerAspect类声明为一个切面
@Order(1)  //设置切面的优先级：如果有多个切面，可通过设置优先级控制切面的执行顺序（数值越小，优先级越高）
@Component
public class LoggerAspect {

    private SysLogMapper sysLogMapper;

    public SysLogMapper getSysLogMapper() {
        return sysLogMapper;
    }
    @Autowired
    public void setSysLogMapper(SysLogMapper sysLogMapper) {
        this.sysLogMapper = sysLogMapper;
    }

    public Logger getLogger() {
        return logger;
    }

    public void setLogger(Logger logger) {
        this.logger = logger;
    }

    private Logger logger = Logger.getLogger(this.getClass());

    @Pointcut("execution(* com.jy.wms.service..*.*(..))")
    public void serviceJoinPointExpression(){}
    /**
     * 前置通知
     * @param joinPoint
     */
    @Before("serviceJoinPointExpression()") //该标签声明次方法是一个前置通知：在目标方法开始之前执行
    public void beforeMethod(JoinPoint joinPoint) throws ClassNotFoundException {
        String methodName = joinPoint.getSignature().getName();

        MethodSignature ms=(MethodSignature) joinPoint.getSignature();
        Method method=ms.getMethod();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        SysUser sysuser= (SysUser) request.getSession().getAttribute(SessionInfo.SessionName);
        BaseServiceDescribe bsd=getServiceMthodDescription(joinPoint);
        if(method.isAnnotationPresent(BaseServiceDescribe.class)){
            //insertLog("1",bsd.moduleName(),bsd.btnName(),"操作"+bsd.moduleName(),"",sysuser.getDlm(),IPUtil.getIpAddress(request),sysuser.getSjk());
        }

        List<Object> args = Arrays.asList(joinPoint.getArgs());
        logger.info("开始调用service:------方法名:"+methodName+"参数为{"+args+"}");
    }

    /**
     * 后置通知
     * @param joinPoint
     */
    @After("serviceJoinPointExpression()")
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        logger.info("结束调用service:------方法名:"+methodName+"参数为{"+args+"}");
    }
    @AfterThrowing(value = "serviceJoinPointExpression()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Throwable e) throws ClassNotFoundException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        SysUser sysuser= (SysUser) request.getSession().getAttribute(SessionInfo.SessionName);
        BaseServiceDescribe bsd=getServiceMthodDescription(joinPoint);
        //this.sysLogService.baseInsert("error",bsd.moduleName(),bsd.btnName(),getExceptionDetail(e),"asdasdas","zzp啊啊啊啊","192.168.5.128","k_jc");
        if(bsd!=null){
            System.out.println("异常了！！！！报错了！！！！");
            logger.error(getExceptionDetail(e));
            insertLog("3",bsd.moduleName(),bsd.btnName(),e.getMessage(),e.getClass().toString(),sysuser.getDlm(), IPUtil.getIpAddress(request),sysuser.getSjk());
        }
    }
    /**
     * 获取注解中对方法的描述信息 用于service层注解
     * @author lyl
     * @param joinPoint
     * @return
     * @throws ClassNotFoundException
     */
    public static BaseServiceDescribe getServiceMthodDescription(JoinPoint joinPoint)
            throws ClassNotFoundException {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        BaseServiceDescribe serviceLog = null;
        for (Method method : methods) {
            if (method.getName().equals(methodName) && method.isAnnotationPresent(BaseServiceDescribe.class)) {
                 serviceLog = method.getAnnotation(BaseServiceDescribe.class);
                break;
            }
        }
        return serviceLog;
    }
    public String getExceptionDetail(Throwable e) {
        StringBuffer stringBuffer = new StringBuffer(e.toString() + "\n");
        StackTraceElement[] messages = e.getStackTrace();
        int length = messages.length;
        for (int i = 0; i < length; i++) {
            stringBuffer.append(messages[i].toString()+"\n");
        }
        return stringBuffer.toString();
    }
    public void insertLog(String jd,String mk,String an,String xx,String ycyy,String dlm,String ip,String database){
        SysLog entity = new SysLog();
        SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        entity.setId(UUIDUtils.uuid());
        entity.setJlsj(sdf.format(new Date()));
        entity.setJb(jd);
        entity.setMk(mk);
        entity.setAn(an);
        entity.setXx(xx);
        entity.setYcyy(ycyy);
        entity.setDlm(dlm);
        entity.setIp(ip);
        try {
            this.sysLogMapper.baseInsert(entity,database);

        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
